#pragma once

#include <string>
#include <pthread.h>
#include <functional>
#include "Log.h"

namespace zmh
{
    class Thread
    {
        static void *Routine(void *argc)
        {
            ((Thread *)argc)->_func(); // 忽略返回值
            return (void *)(0);
        }

    public:
        Thread() = default;
        Thread(Thread &) = delete;
        Thread &operator=(Thread &) = delete;
        Thread(const Thread &) = delete;
        Thread &operator=(const Thread &) = delete;

        Thread(Thread &&t) noexcept
        {
            // step1 --- 资源窃取
            _id = t._id;
            _func = std::move(t._func);
            _joinable = t._joinable;
            // step2 --- 修改t线程的状态
            t._joinable = false; // _joinable标识了该thread类对象是否管理了某个线程
        }
        Thread &operator=(Thread &&t) noexcept
        {
            if (_joinable == true) // this正管理着线程
                LOG(zmh::INFO) << "this正管理着线程" << _id << ",已将其分离,后让其管理新的线程";

            // step1 --- 资源窃取
            _id = t._id;
            _func = std::move(t._func);
            _joinable = t._joinable;
            // step2 --- 修改t线程的状态
            t._joinable = false; // _joinable标识了该thread类对象是否管理了某个线程

            return *this;
        }
        template <class Fn, class... Args>
        explicit Thread(Fn &&func, Args &&...args)
        {
            // step1 --- 回调函数处理 --- bind默认是值绑定,引用绑定需要std::ref(argu),为了代码健壮性,选择交给用户
            _func = std::bind(std::forward<Fn>(func), std::forward<Args>(args)...);
            // step2 --- 创建线程
            int n = pthread_create(&_id, nullptr, Routine, this);
            // step3 --- 线程创建成功，再更新_flag
            if (n == 0)
                _joinable = true;
        }
        ~Thread()
        {
            if (_joinable)
            {
                LOG(zmh::INFO) << "线程可被等待,可用户未主动等待,已终止程序";
                // 需要被等待，但用户未主动等待 直接终止程序
                exit(-1);
            }
        }
        void join()
        {
            if (_joinable)
            {
                pthread_join(_id, nullptr);
                _joinable = false;
            }
        }
        void detach()
        {
            if (_joinable)
            {
                pthread_detach(_id);
                _joinable = false;
            }
        }
        void cancel()
        {
            pthread_cancel(_id);
            _joinable = false;
        }
        unsigned long long get_id()
        {
            return _id;
        }
        bool joinable()
        {
            return _joinable;
        }

    private:
        pthread_t _id = (pthread_t) false;     // 线程id
        bool _joinable = false;                // 能否被等待 --- 该类是否正在管理某个线程
        std::function<void()> _func = nullptr; // 回调函数的地址
    };
}